﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;

using System.Linq.Expressions;
using DoNet.FrameWork.DomainModel;
using DoNet.FrameWork.Repository.Specification;
using System.Data.Entity.ModelConfiguration.Conventions;
using System.Data.Entity.Infrastructure;
using System.Data.Entity;

namespace DoNet.FrameWork.Repository.Impl
{
    public abstract class RepositoryBase<T> : IRepository<T, PageData<T>> where T : Entity
    {
        /// <summary>
        /// 公用的数据上下文
        /// </summary>
        public MISEntities context;

        public RepositoryBase(IUnitOfWork _UnitOfWork)
        {
            context = _UnitOfWork as MISEntities;
        }

        /// <summary>
        /// 数据分页的方法
        /// </summary>
        /// <typeparam name="S"></typeparam>
        /// <param name="PageIndex">当前页码</param>
        /// <param name="PageSize">每页显示条数</param>
        /// <param name="condition">数据查询条件表达式</param>
        /// <param name="orderByExpression">排序的条件表达式</param>
        /// <param name="IsDESC">是否为倒序</param>
        /// <returns></returns>
        public PageData<T> FindAll<S>(int PageIndex, int PageSize, ISpecification<T> condition, Expression<Func<T, S>> orderByExpression, bool IsDESC)
        {
            var query = IsDESC
                ?
                (context.Set<T>()).Where(condition.SatisfiedBy()).OrderByDescending(orderByExpression)
                :
                (context.Set<T>()).Where(condition.SatisfiedBy()).OrderBy(orderByExpression);

            PageData<T> pageData = new PageData<T>();
            pageData.TotalCount = query.Count();
            pageData.DataList = query.Skip((PageIndex - 1) * PageSize).Take(PageSize).ToList();

            return pageData;
        }

        /// <summary>
        /// 得到所有数据
        /// </summary>
        /// <returns></returns>
        public List<T> GetList()
        {
            return (context.Set<T>()).ToList<T>();
        }

        /// <summary>
        /// 根据条件表达式取得相关数据
        /// </summary>
        /// <param name="condition">Lambda表达式</param>
        /// <returns></returns>
        public List<T> GetList(ISpecification<T> condition)
        {

            var query = (context.Set<T>()).Where(condition.SatisfiedBy());

            return query.ToList();

        }

        /// <summary>
        /// 根据条件表达式取得相关数据并排序
        /// </summary>
        /// <param name="condition">Lambda表达式</param>
        /// <returns></returns>
        public List<T> GetList<S>(ISpecification<T> condition, Expression<Func<T, S>> orderByExpression, bool IsDESC)
        {

            var query = IsDESC
                ?
                (context.Set<T>()).Where(condition.SatisfiedBy()).OrderByDescending(orderByExpression)
                :
                (context.Set<T>()).Where(condition.SatisfiedBy()).OrderBy(orderByExpression);

            return query.ToList();
        }

        /// <summary>
        /// 根据条件表达式取得指定条数的数据
        /// </summary>
        /// <typeparam name="S"></typeparam>
        /// <param name="TopN">返回的数据条数</param>
        /// <param name="condition">Lambda表达式</param>
        /// <param name="orderByExpression">Lambda表达式</param>
        /// <param name="IsDESC"></param>
        /// <returns></returns>
        public List<T> GetListByTopN<S>(int TopN, ISpecification<T> condition, Expression<Func<T, S>> orderByExpression, bool IsDESC)
        {

            var query = IsDESC
                ?
                (context.Set<T>()).Where(condition.SatisfiedBy()).OrderByDescending(orderByExpression).Take(TopN)
                :
                (context.Set<T>()).Where(condition.SatisfiedBy()).OrderBy(orderByExpression).Take(TopN);

            return query.ToList();

        }

        /// <summary>
        /// 返回指定条件的数据
        /// </summary>
        /// <param name="condition"></param>
        /// <returns></returns>
        public T GetByCondition(ISpecification<T> condition)
        {
            T result = context.Set<T>().Local.AsQueryable().Where(condition.SatisfiedBy())
                .AsNoTracking().FirstOrDefault();

            if (result == null)
            return (context.Set<T>()).Where(condition.SatisfiedBy())
                .AsNoTracking().FirstOrDefault();
            else
                return result;

            //return (context.Set<T>()).Where(condition.SatisfiedBy())
            //    .AsNoTracking().FirstOrDefault();

            //this.LoadReference(query);

        }

        /// <summary>
        /// 将实体数据保存到数据库中
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public void NewSave(T model)
        {

            (context.Set<T>()).Add(model);
            context.Entry<T>(model).State = EntityState.Added;
        }

        /// <summary>
        /// 更新数据数据库中的一条数据  根据主键值
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public void Modify(T model)
        {
            var entry = context.Entry<T>(model);
            if (entry.State == EntityState.Detached)
            {
                var modelToUpdate = context.Set<T>().Find(model.Id);
                //EmitMapper.ObjectMapperManager.DefaultInstance.GetMapper<T, T>().Map(model, entityToUpdate);
                context.Entry<T>(modelToUpdate).State = EntityState.Modified;
            }
            //if (context.Entry<T>(model).State != EntityState.Modified)
            //{
            //}
        }

        /// <summary>
        /// 从数据库中删除数据   仅用于同一上下文的集合对象有效
        /// </summary>
        /// <param name="model"></param>
        /// <returns></returns>
        public void Remove(T model)
        {
            if (model != null)
            {
                context.Set<T>().Remove(model);
                context.Entry<T>(model).State = EntityState.Deleted;
            }
        }

        /// <summary>
        /// 删除指定条件的数据 最多删除一条
        /// </summary>
        /// <param name="condition"></param>
        /// <returns></returns>
        public void Remove(ISpecification<T> condition)
        {
            var query = (context.Set<T>()).Where(condition.SatisfiedBy()).FirstOrDefault();
            if (query != null)
            {
                context.Set<T>().Remove(query);
                context.Entry<T>(query).State = EntityState.Deleted;
            }
        }

        /// <summary>
        /// 删除指定条件的数据
        /// </summary>
        /// <param name="condition"></param>
        /// <returns></returns>
        public void Removes(ISpecification<T> condition)
        {
            var query = (context.Set<T>()).Where(condition.SatisfiedBy());
            if (query != null)
            {
                //批量操作前 关闭自动检测变化功能
                context.Configuration.AutoDetectChangesEnabled = false;
                foreach (var q in query)
                {
                    context.Set<T>().Remove(q);
                    context.Entry<T>(q).State = EntityState.Deleted;
                }
                //开启自动检测变化
                context.Configuration.AutoDetectChangesEnabled = true;
            }
        }

        //public void LocalClear()
        //{
        //    context.Set<T>().Local.Clear();
        //}

        /// <summary>
        /// 提交数据变更
        /// </summary>
        /// <returns></returns>
        public int SaveChanges()
        {
            return context.SaveChanges();
        }
    }

}

